import { openWindow } from '..';
import { dataURLtoBlob, urlToBase64 } from './base64Conver';

/**
 * 根据在线图片URL下载图片，下载过程是异步的
 * @param url 图片的URL
 * @param filename 下载后的文件名
 * @param mime 文件的MIME类型，可选
 * @param bom BOM数据，可选
 */
export function downloadByOnlineUrl(url: string, filename: string, mime?: string, bom?: BlobPart) {
  urlToBase64(url).then((base64) => {
    downloadByBase64(base64, filename, mime, bom);
  });
}

/**
 * 根据base64下载图片
 * @param buf base64字符串
 * @param filename 下载后的文件名
 * @param mime 文件的MIME类型，可选
 * @param bom BOM数据，可选
 */
export function downloadByBase64(buf: string, filename: string, mime?: string, bom?: BlobPart) {
  const base64Buf = dataURLtoBlob(buf);
  downloadByData(base64Buf, filename, mime, bom);
}

/**
 * 根据后台接口文件流来下载
 * @param data 需要下载的数据 (BlobPart)，可以是ArrayBuffer, ArrayBufferView (Uint8Array等), Blob, DOMString等
 * @param filename 下载后的文件名
 * @param mime 文件的MIME类型，如果没有定义，将会默认为 ‘application/octet-stream’
 * @param bom BOM数据，用于定义文件的编码方式 (例如 UTF-8, UTF-16), 通常不需要定义
 */
export function downloadByData(data: BlobPart, filename: string, mime?: string, bom?: BlobPart) {
  const blobData = typeof bom !== 'undefined' ? [bom, data] : [data];
  const blob = new Blob(blobData, { type: mime || 'application/octet-stream' });

  //createObjectURL 方法来创建一个文件下载链接，这种方法也是非阻塞性的，即它不会阻塞JavaScript执行或者浏览器的渲染进程。
  const blobURL = window.URL.createObjectURL(blob);
  const tempLink = document.createElement('a');
  tempLink.style.display = 'none';
  tempLink.href = blobURL;
  tempLink.setAttribute('download', filename);
  if (typeof tempLink.download === 'undefined') {
    tempLink.setAttribute('target', '_blank');
  }
  document.body.appendChild(tempLink);
  tempLink.click();
  document.body.removeChild(tempLink);
  window.URL.revokeObjectURL(blobURL);
}

/**
 * 根据文件地址下载文件，通用性不如downloadFileByUrl，仅支持Chrome和Safari，尽量使用downloadFileByUrl
 * @param sUrl 文件URL
 * @param target 下载的目标，可选，默认为'_blank'
 * @param fileName 下载后的文件名，可选
 */
export function downloadByUrl({
  url,
  target = '_blank',
  fileName,
}: {
  url: string;
  target?: TargetContext;
  fileName?: string;
}): boolean {
  const isChrome = window.navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
  const isSafari = window.navigator.userAgent.toLowerCase().indexOf('safari') > -1;

  if (/(iP)/g.test(window.navigator.userAgent)) {
    console.error('您的浏览器不支持下载功能！');
    return false;
  }
  if (isChrome || isSafari) {
    const link = document.createElement('a');
    link.href = url;
    link.target = target;

    if (link.download !== undefined) {
      link.download = fileName || url.substring(url.lastIndexOf('/') + 1, url.length);
    }

    if (document.createEvent) {
      const e = document.createEvent('MouseEvents');
      e.initEvent('click', true, true);
      link.dispatchEvent(e);
      return true;
    }
  }
  if (url.indexOf('?') === -1) {
    url += '?download';
  }

  openWindow(url, { target });
  return true;
}

/**
 * 根据URL下载文件，这是异步下载方法，不会因为文件下载而导致整个应用或页面冻结
 * @param url 待下载文件的URL地址
 * @param filename 指定下载后的文件名
 */
export async function downloadFileByUrl(url: string, filename: string): Promise<void> {
  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const blob = await response.blob();
    const downloadUrl = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = downloadUrl;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    window.URL.revokeObjectURL(downloadUrl);
    document.body.removeChild(a);
  } catch (error) {
    console.error('下载文件失败：', error);
  }
}
